package org.dftproject.genesis.ui.pages.circlediagram;

import org.dftproject.genesis.data.genealogy.Sex;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;

public class CircleDiagramIconFigure extends Figure {

	public final Color borderColor = new Color(null, 0x88, 0x88, 0x88);
	private final Color maleColor = new Color(null, 0xBB, 0xBB, 0xFF);
	private final Color femaleColor = new Color(null, 0xFF, 0xBB, 0xBB);
	
	private final int generations = 4;
	
	private final CircleDiagramNode root;
	
	public CircleDiagramIconFigure() {		
		root = new CircleDiagramNode(null, null, Sex.Male, null);
		addParents(root, 2);
		root.getLeft().getLeft().setLeft(new CircleDiagramNode(null, null, Sex.Male, null));
		root.getLeft().getRight().setRight(new CircleDiagramNode(null, null, Sex.Female, null));
		root.getRight().getLeft().setRight(new CircleDiagramNode(null, null, Sex.Female, null));
	}
	
	protected void addParents(CircleDiagramNode child, int generations) {
		CircleDiagramNode left = new CircleDiagramNode(null, null, Sex.Male, null);
		child.setLeft(left);
		if (generations > 1)
			addParents(left, generations - 1);
		
		CircleDiagramNode right = new CircleDiagramNode(null, null, Sex.Female, null);
		child.setRight(right);
		if (generations > 1)
			addParents(right, generations - 1);
	}

	@Override
	public void paintFigure(Graphics graphics) {
		super.paintFigure(graphics);
		
		if (root != null) {
			graphics.pushState();
			graphics.translate(getBounds().getCenter());

			paintNode(graphics, root, 0, 0);

			graphics.popState();
		}
	}

	protected void paintNode(Graphics graphics, CircleDiagramNode node, int row, int column) {
		if (row < generations - 1) {
			if (node.getLeft() != null)
				paintNode(graphics, node.getLeft(), row + 1, column * 2);
			if (node.getRight() != null)
				paintNode(graphics, node.getRight(), row + 1, column * 2 + 1);
		}

		graphics.pushState();

		double scale = Math.min(getBounds().width - 2, getBounds().height - 2) / (2.0 * generations);
		double radius = scale * (row + 1);

		Rectangle bounds = new Rectangle((int) -radius, (int) -radius, (int) (2 * radius), (int) (2 * radius));

		graphics.setBackgroundColor(node.getSex() == Sex.Male ? maleColor : femaleColor);

		if (row == 0) {
			graphics.setAntialias(SWT.OFF);
			graphics.fillOval(bounds.getResized(1, 1));

			graphics.setForegroundColor(borderColor);
			graphics.setAntialias(SWT.ON);
			
			graphics.drawOval(bounds);
		} else {
			int columns = (int) Math.pow(2, row);
			double[] thetas = new double[2];

			float arcLength = -360.0f / columns;
			float arcOffset = -90.0f + arcLength * column;

			graphics.setAntialias(SWT.OFF);
			GraphicsUtils.fillArc(graphics, bounds.getResized(1, 1), arcOffset, arcLength, (int) scale);

			graphics.setAntialias(SWT.ON);

			thetas[0] = arcOffset * Math.PI / 180.0;
			thetas[1] = (arcOffset + arcLength) * Math.PI / 180.0;

			graphics.setForegroundColor(borderColor);
			GraphicsUtils.drawArc(graphics, bounds, arcOffset, arcLength);

			double innerRadius = scale * row;
			for (int i = 0; i < thetas.length; i++) {
				Point p1 = new Point(radius * Math.cos(thetas[i]), -radius * Math.sin(thetas[i]));
				Point p2 = new Point(innerRadius * Math.cos(thetas[i]), -innerRadius * Math.sin(thetas[i]));
				graphics.drawLine(p1, p2);
			}
		}

		graphics.popState();
	}
	
}
